package com.hz.tgb.response.restful.exception.handler;

import com.hz.tgb.response.restful.ResponseData;
import com.hz.tgb.response.restful.exception.AbstractException;
import com.hz.tgb.response.restful.exception.ErrorException;
import com.hz.tgb.response.restful.exception.InfoException;
import com.hz.tgb.response.restful.exception.WarnException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * 异常拦截封装
 *
 * @author hezhao on 2019/8/28 18:04
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseData<String> baseErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        ResponseData<String> result;

        // 异常级别: 1-info, 2-warn, 3-error
        int exceptionLevel = 3;

        if (InfoException.class.isAssignableFrom(e.getClass())) {
            result = data((InfoException) e);
            exceptionLevel = 1;
        } else if (WarnException.class.isAssignableFrom(e.getClass())) {
            result = data((WarnException) e);
            exceptionLevel = 2;
        } else if (ErrorException.class.isAssignableFrom(e.getClass())) {
            result = data((ErrorException) e);
        } else if (AbstractException.class.isAssignableFrom(e.getClass())) {
            result = data((AbstractException) e);
        }  else {
            result = new ResponseData<>();
            result.setMsg(e.getMessage());
        }

        if (exceptionLevel == 1) {
            logger.info("Exception Handler：Host {} invokes url {} ERROR: {}", req.getRemoteHost(), req.getRequestURL(), e.getMessage());
            logger.info("process is error!", e);
        } else if (exceptionLevel == 2) {
            logger.warn("Exception Handler：Host {} invokes url {} ERROR: {}", req.getRemoteHost(), req.getRequestURL(), e.getMessage());
            logger.warn("process is error!", e);
        } else {
            logger.error("Exception Handler：Host {} invokes url {} ERROR: {}", req.getRemoteHost(), req.getRequestURL(), e.getMessage());
            logger.error("process is error!", e);
        }

        result.setTraceId("// TODO context.getTraceId()");
        return result;
    }

    private <T extends AbstractException> ResponseData<String> data(T ex) {
        ResponseData<String> result = new ResponseData<>(ex.getAppCode());
        result.setMsg(result.getMsg());
        return result;
    }
}